A Swift Tour

                  print("Hello, world!")

// Prints "Hello, world!"
                
                    println("Hello, world!")

// Prints "Hello, world!"
                  

Simple Values

                  var myVariable = 42

myVariable = 50

let myConstant = 42
                
                    var myVariable = 42

myVariable = 50

val myConstant = 42
                  
                  let implicitInteger = 70

let implicitDouble = 70.0

let explicitDouble: Double = 70
                
                    val implicitInteger = 70

val implicitDouble = 70.0

val explicitDouble: Double = 70
                  
                  let label = "The width is "

let width = 94

let widthLabel = label + String(width)
                
                    val label = "The width is "

val width = 94

val widthLabel = label + width.toString()

                  
                  let apples = 3

let oranges = 5

let appleSummary = "I have \(apples) apples."

let fruitSummary = "I have \(apples + oranges) pieces of fruit."
                
                  let quotation = """

I said "I have \(apples) apples."

And then I said "I have \(apples + oranges) pieces of fruit."

"""
                
                  var shoppingList = ["catfish", "water", "tulips"]

shoppingList[1] = "bottle of water"



var occupations = [

    "Malcolm": "Captain",

    "Kaylee": "Mechanic",

]

occupations["Jayne"] = "Public Relations"
                
                  shoppingList.append("blue paint")

print(shoppingList)
                
                  let emptyArray = [String]()

let emptyDictionary = [String: Float]()
                
                  shoppingList = []

occupations = [:]
                

Control Flow

                  let individualScores = [75, 43, 103, 87, 12]

var teamScore = 0

for score in individualScores {

    if score > 50 {

        teamScore += 3

    } else {

        teamScore += 1

    }

}

print(teamScore)

// Prints "11"
                
                  var optionalString: String? = "Hello"

print(optionalString == nil)

// Prints "false"



var optionalName: String? = "John Appleseed"

var greeting = "Hello!"

if let name = optionalName {

    greeting = "Hello, \(name)"

}
                
                  let nickname: String? = nil

let fullName: String = "John Appleseed"

let informalGreeting = "Hi \(nickname ?? fullName)"
                
                  let vegetable = "red pepper"

switch vegetable {

case "celery":

    print("Add some raisins and make ants on a log.")

case "cucumber", "watercress":

    print("That would make a good tea sandwich.")

case let x where x.hasSuffix("pepper"):

    print("Is it a spicy \(x)?")

default:

    print("Everything tastes good in soup.")

}

// Prints "Is it a spicy red pepper?"
                
                  let interestingNumbers = [

    "Prime": [2, 3, 5, 7, 11, 13],

    "Fibonacci": [1, 1, 2, 3, 5, 8],

    "Square": [1, 4, 9, 16, 25],

]

var largest = 0

for (kind, numbers) in interestingNumbers {

    for number in numbers {

        if number > largest {

            largest = number

        }

    }

}

print(largest)

// Prints "25"
                
                  var n = 2

while n < 100 {

    n *= 2

}

print(n)

// Prints "128"



var m = 2

repeat {

    m *= 2

} while m < 100

print(m)

// Prints "128"
                
                  var total = 0

for i in 0..<4 {

    total += i

}

print(total)

// Prints "6"
                

Functions and Closures

                  func greet(person: String, day: String) -> String {

    return "Hello \(person), today is \(day)."

}

greet(person: "Bob", day: "Tuesday")
                
                  func greet(_ person: String, on day: String) -> String {

    return "Hello \(person), today is \(day)."

}

greet("John", on: "Wednesday")
                
                  func calculateStatistics(scores: [Int]) -> (min: Int, max: Int, sum: Int) {

    var min = scores[0]

    var max = scores[0]

    var sum = 0



    for score in scores {

        if score > max {

            max = score

        } else if score < min {

            min = score

        }

        sum += score

    }



    return (min, max, sum)

}

let statistics = calculateStatistics(scores: [5, 3, 100, 3, 9])

print(statistics.sum)

// Prints "120"

print(statistics.2)

// Prints "120"
                
                  func returnFifteen() -> Int {

    var y = 10

    func add() {

        y += 5

    }

    add()

    return y

}

returnFifteen()
                
                  func makeIncrementer() -> ((Int) -> Int) {

    func addOne(number: Int) -> Int {

        return 1 + number

    }

    return addOne

}

var increment = makeIncrementer()

increment(7)
                
                  func hasAnyMatches(list: [Int], condition: (Int) -> Bool) -> Bool {

    for item in list {

        if condition(item) {

            return true

        }

    }

    return false

}

func lessThanTen(number: Int) -> Bool {

    return number < 10

}

var numbers = [20, 19, 7, 12]

hasAnyMatches(list: numbers, condition: lessThanTen)
                
                  numbers.map({ (number: Int) -> Int in

    let result = 3 * number

    return result

})
                
                  let mappedNumbers = numbers.map({ number in 3 * number })

print(mappedNumbers)

// Prints "[60, 57, 21, 36]"
                
                  let sortedNumbers = numbers.sorted { $0 > $1 }

print(sortedNumbers)

// Prints "[20, 19, 12, 7]"
                

Objects and Classes

                  class Shape {

    var numberOfSides = 0

    func simpleDescription() -> String {

        return "A shape with \(numberOfSides) sides."

    }

}
                
                  var shape = Shape()

shape.numberOfSides = 7

var shapeDescription = shape.simpleDescription()
                
                  class NamedShape {

    var numberOfSides: Int = 0

    var name: String



    init(name: String) {

        self.name = name

    }



    func simpleDescription() -> String {

        return "A shape with \(numberOfSides) sides."

    }

}
                
                  class Square: NamedShape {

    var sideLength: Double



    init(sideLength: Double, name: String) {

        self.sideLength = sideLength

        super.init(name: name)

        numberOfSides = 4

    }



    func area() -> Double {

        return sideLength * sideLength

    }



    override func simpleDescription() -> String {

        return "A square with sides of length \(sideLength)."

    }

}

let test = Square(sideLength: 5.2, name: "my test square")

test.area()

test.simpleDescription()
                
                  class EquilateralTriangle: NamedShape {

    var sideLength: Double = 0.0



    init(sideLength: Double, name: String) {

        self.sideLength = sideLength

        super.init(name: name)

        numberOfSides = 3

    }



    var perimeter: Double {

        get {

            return 3.0 * sideLength

        }

        set {

            sideLength = newValue / 3.0

        }

    }



    override func simpleDescription() -> String {

        return "An equilateral triangle with sides of length \(sideLength)."

    }

}

var triangle = EquilateralTriangle(sideLength: 3.1, name: "a triangle")

print(triangle.perimeter)

// Prints "9.3"

triangle.perimeter = 9.9

print(triangle.sideLength)

// Prints "3.3000000000000003"
                
                  class TriangleAndSquare {

    var triangle: EquilateralTriangle {

        willSet {

            square.sideLength = newValue.sideLength

        }

    }

    var square: Square {

        willSet {

            triangle.sideLength = newValue.sideLength

        }

    }

    init(size: Double, name: String) {

        square = Square(sideLength: size, name: name)

        triangle = EquilateralTriangle(sideLength: size, name: name)

    }

}

var triangleAndSquare = TriangleAndSquare(size: 10, name: "another test shape")

print(triangleAndSquare.square.sideLength)

// Prints "10.0"

print(triangleAndSquare.triangle.sideLength)

// Prints "10.0"

triangleAndSquare.square = Square(sideLength: 50, name: "larger square")

print(triangleAndSquare.triangle.sideLength)

// Prints "50.0"
                
                  let optionalSquare: Square? = Square(sideLength: 2.5, name: "optional square")

let sideLength = optionalSquare?.sideLength
                

Enumerations and Structures

                  enum Rank: Int {

    case ace = 1

    case two, three, four, five, six, seven, eight, nine, ten

    case jack, queen, king



    func simpleDescription() -> String {

        switch self {

        case .ace:

            return "ace"

        case .jack:

            return "jack"

        case .queen:

            return "queen"

        case .king:

            return "king"

        default:

            return String(self.rawValue)

        }

    }

}

let ace = Rank.ace

let aceRawValue = ace.rawValue
                
                  if let convertedRank = Rank(rawValue: 3) {

    let threeDescription = convertedRank.simpleDescription()

}
                
                  enum Suit {

    case spades, hearts, diamonds, clubs



    func simpleDescription() -> String {

        switch self {

        case .spades:

            return "spades"

        case .hearts:

            return "hearts"

        case .diamonds:

            return "diamonds"

        case .clubs:

            return "clubs"

        }

    }

}

let hearts = Suit.hearts

let heartsDescription = hearts.simpleDescription()
                
                  enum ServerResponse {

    case result(String, String)

    case failure(String)

}



let success = ServerResponse.result("6:00 am", "8:09 pm")

let failure = ServerResponse.failure("Out of cheese.")



switch success {

case let .result(sunrise, sunset):

    print("Sunrise is at \(sunrise) and sunset is at \(sunset).")

case let .failure(message):

    print("Failure...  \(message)")

}

// Prints "Sunrise is at 6:00 am and sunset is at 8:09 pm."
                
                  struct Card {

    var rank: Rank

    var suit: Suit

    func simpleDescription() -> String {

        return "The \(rank.simpleDescription()) of \(suit.simpleDescription())"

    }

}

let threeOfSpades = Card(rank: .three, suit: .spades)

let threeOfSpadesDescription = threeOfSpades.simpleDescription()
                

Protocols and Extensions

                  protocol ExampleProtocol {

    var simpleDescription: String { get }

    mutating func adjust()

}
                
                  class SimpleClass: ExampleProtocol {

    var simpleDescription: String = "A very simple class."

    var anotherProperty: Int = 69105

    func adjust() {

        simpleDescription += "  Now 100% adjusted."

    }

}

var a = SimpleClass()

a.adjust()

let aDescription = a.simpleDescription



struct SimpleStructure: ExampleProtocol {

    var simpleDescription: String = "A simple structure"

    mutating func adjust() {

        simpleDescription += " (adjusted)"

    }

}

var b = SimpleStructure()

b.adjust()

let bDescription = b.simpleDescription
                
                  extension Int: ExampleProtocol {

    var simpleDescription: String {

        return "The number \(self)"

    }

    mutating func adjust() {

        self += 42

    }

}

print(7.simpleDescription)

// Prints "The number 7"
                
                  let protocolValue: ExampleProtocol = a

print(protocolValue.simpleDescription)

// Prints "A very simple class.  Now 100% adjusted."

// print(protocolValue.anotherProperty)  // Uncomment to see the error
                

Error Handling

                  enum PrinterError: Error {

    case outOfPaper

    case noToner

    case onFire

}
                
                  func send(job: Int, toPrinter printerName: String) throws -> String {

    if printerName == "Never Has Toner" {

        throw PrinterError.noToner

    }

    return "Job sent"

}
                
                  do {

    let printerResponse = try send(job: 1040, toPrinter: "Bi Sheng")

    print(printerResponse)

} catch {

    print(error)

}

// Prints "Job sent"
                
                  do {

    let printerResponse = try send(job: 1440, toPrinter: "Gutenberg")

    print(printerResponse)

} catch PrinterError.onFire {

    print("I'll just put this over here, with the rest of the fire.")

} catch let printerError as PrinterError {

    print("Printer error: \(printerError).")

} catch {

    print(error)

}

// Prints "Job sent"
                
                  let printerSuccess = try? send(job: 1884, toPrinter: "Mergenthaler")

let printerFailure = try? send(job: 1885, toPrinter: "Never Has Toner")
                
                  var fridgeIsOpen = false

let fridgeContent = ["milk", "eggs", "leftovers"]



func fridgeContains(_ food: String) -> Bool {

    fridgeIsOpen = true

    defer {

        fridgeIsOpen = false

    }



    let result = fridgeContent.contains(food)

    return result

}

fridgeContains("banana")

print(fridgeIsOpen)

// Prints "false"
                

Generics

                  func makeArray<Item>(repeating item: Item, numberOfTimes: Int) -> [Item] {

    var result = [Item]()

    for _ in 0..<numberOfTimes {

        result.append(item)

    }

    return result

}

makeArray(repeating: "knock", numberOfTimes: 4)
                
                  // Reimplement the Swift standard library's optional type

enum OptionalValue<Wrapped> {

    case none

    case some(Wrapped)

}

var possibleInteger: OptionalValue<Int> = .none

possibleInteger = .some(100)
                
                  func anyCommonElements<T: Sequence, U: Sequence>(_ lhs: T, _ rhs: U) -> Bool

    where T.Element: Equatable, T.Element == U.Element

{

    for lhsItem in lhs {

        for rhsItem in rhs {

            if lhsItem == rhsItem {

                return true

            }

        }

    }

    return false

}

anyCommonElements([1, 2, 3], [3])